// AudioDX.cpp: implementation of the CAudioDX class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "AudioDX.h"

#include "audiodef.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////


#define SAFE_DELETE(p)  { if(p) { delete (p);     (p)=NULL; } }
#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
#define DXTRACE			TRACE



CAudioDX::CAudioDX()
{
	bDXAudioInitialized = FALSE;
	pDS8		= NULL;
	hWindow		= NULL;
	PacketSize	= 0;
	m_waveformat = tblWaveFormat[PCM_8BIT_8KHZ_MONO];
	
}

CAudioDX::~CAudioDX()
{

}

HRESULT CAudioDX::InitializeAudio( HWND hWnd )
{	
	HRESULT hr;
//	DSBUFFERDESC dsbd;

	hWindow = hWnd;

	try
	{
    if( FAILED( hr = CoInitialize(NULL) ) )
        return DXTRACE_ERR( TEXT("CoInitialize"), hr );

	// Create IDirectSound using the preferred sound device
	if( FAILED( hr = DirectSoundCreate8( NULL, &pDS8, NULL ) ) )
	{
		CoUninitialize( );
		return DXTRACE_ERR( TEXT("DirectSoundCreate"), hr );
	}

    // Set coop level to DSSCL_PRIORITY
    if( FAILED( hr = pDS8->SetCooperativeLevel( hWnd, DSSCL_NORMAL ) ) )
	{
		SAFE_RELEASE( pDS8 ); 
		CoUninitialize( );
        return DXTRACE_ERR( TEXT("SetCooperativeLevel"), hr );
	}
/*
    // Obtain primary buffer 
    ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
    dsbd.dwSize  = sizeof(DSBUFFERDESC);
    dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;

    if( FAILED( hr = pDS8->CreateSoundBuffer( &dsbd, &pDSBPrimary, NULL ) ) )
	{
		SAFE_RELEASE( pDS8 ); 
		CoUninitialize( );
        return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr );
	}
*/
	}
	catch(...)
	{

		throw S_FALSE;
	}
	bDXAudioInitialized = TRUE;

	return S_OK;
}

void CAudioDX::FinalizeAudio( )
{
	if( !bDXAudioInitialized )
		return;
	bDXAudioInitialized = FALSE;
	hWindow = NULL;
//	SAFE_RELEASE( pDSBPrimary );
	SAFE_RELEASE( pDS8 ); 
	CoUninitialize();
}


XAUDIOINFO *CAudioDX::GetPlayerInfo( )
{
	DXPLAYERINFO *ppi = new DXPLAYERINFO;
	if( ppi )
	{
		ZeroMemory( ppi, sizeof(DXPLAYERINFO) );
		ppi->hNotificationEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
	}
	return (XAUDIOINFO*)ppi;
}

void CAudioDX::ReleasePlayerInfo( XAUDIOINFO *pai )
{
	DXPLAYERINFO *ppi = (DXPLAYERINFO *)pai;
	if( ppi->hNotificationEvent )
	{
		CloseHandle(ppi->hNotificationEvent);
	}
	if( ppi ) 
	{
		delete ppi;
	}
	ppi = NULL;
}

HRESULT CAudioDX::InitializePlayer( XAUDIOINFO *pai )
{   
	HRESULT             hr;
	DSBUFFERDESC        dsbd;
	DXPLAYERINFO *ppi = (DXPLAYERINFO *)pai;
	int				nSampleFormat= ppi->nSampleFormat;

    ZeroMemory( &ppi->aPosNotify, sizeof(DSBPOSITIONNOTIFY) * 
                               (NUM_PLAY_NOTIFICATIONS) );
    ppi->dwOutputBufferSize  = 0;
    ppi->dwNotifySize        = 0;
	ppi->dwNextOutputOffset = 0;

 	m_waveformat = tblWaveFormat[nSampleFormat];

    //ppi->dwNextOutputOffset  = 0;

	//ppi->hNotificationEvent = CreateEvent( NULL, FALSE, FALSE, NULL );

    // Set the format of the primary buffer 
    // to the format of the output buffer
	//if( FAILED( hr = pDSBPrimary->SetFormat( &wfx[ppi->nSampleFormat] ) ) )
	//	return DXTRACE_ERR( TEXT("Primary SetFormat"), hr );

	//DWORD fmtlen;
	//WAVEFORMATEX wfmt;
	//if( FAILED( hr = pDSBPrimary->GetFormat( &wfmt, sizeof(WAVEFORMATEX), &fmtlen ) ) )
	//	return DXTRACE_ERR( TEXT("Primary GetFormat"), hr );

	try
	{
#if 1
		ppi->dwNotifySize = PacketSize;
		ppi->dwNotifySize -= ppi->dwNotifySize % tblWaveFormat[nSampleFormat].nBlockAlign;
#else
	if( ppi->nCodec==AUDIO_PCM )
	{
		ppi->dwNotifySize = PacketSize;
		ppi->dwNotifySize -= ppi->dwNotifySize % tblWaveFormat[nSampleFormat].nBlockAlign;
	}
	else if( ppi->nCodec==AUDIO_ADPCM )
	{
		//ppi->dwPlayLossSize = (DEFAULT_PACKET_SIZE>>2);// loss in 1/8
		ppi->dwPlayLossSize = 0;
		ppi->dwNotifySize = (PacketSize<<2) - ppi->dwPlayLossSize; 
		ppi->dwNotifySize -= ppi->dwNotifySize % tblWaveFormat[nSampleFormat].nBlockAlign;
	}
	else if( ppi->nCodec==AUDIO_G723 )
	{
		ppi->pG723Obj = g723_decoder_alloc( );
		ppi->dwNotifySize = G723_RawBlockBytes; // 4800 20:1  g723
		ppi->dwNotifySize -= ppi->dwNotifySize % tblWaveFormat[nSampleFormat].nBlockAlign;
	}
	else if( ppi->nCodec==AUDIO_MULAW )
	{
		ppi->dwNotifySize =  PacketSize << 1;
		
		m_waveformat.wFormatTag = WAVE_FORMAT_PCM;
		m_waveformat.nAvgBytesPerSec <<= 1;
		m_waveformat.nBlockAlign <<= 1;
		m_waveformat.wBitsPerSample <<=1;
		//nSampleFormat = PCM_16BIT_8KHZ_MONO;
		ppi->dwNotifySize -= ppi->dwNotifySize % m_waveformat.nBlockAlign;		
		
	}
	else if( ppi->nCodec==AUDIO_ALAW )
	{
		ppi->dwNotifySize =  PacketSize << 1;
		//nSampleFormat = PCM_16BIT_8KHZ_MONO;
		m_waveformat.wFormatTag = WAVE_FORMAT_PCM;
		m_waveformat.nAvgBytesPerSec <<= 1;
		m_waveformat.nBlockAlign <<= 1;
		m_waveformat.wBitsPerSample <<=1;
		ppi->dwNotifySize -= ppi->dwNotifySize % m_waveformat.nBlockAlign;		
		
	}
#endif
	// Set the buffer sizes 
	ppi->dwOutputBufferSize  = NUM_PLAY_NOTIFICATIONS * ppi->dwNotifySize;

    // Create the direct sound buffer using the same format as the 
    // capture buffer. 
    ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
    dsbd.dwSize          = sizeof(DSBUFFERDESC);
    dsbd.dwFlags         = DSBCAPS_GLOBALFOCUS|DSBCAPS_CTRLPOSITIONNOTIFY|DSBCAPS_CTRLVOLUME|
							DSBCAPS_CTRLPAN|DSBCAPS_CTRLFREQUENCY|DSBCAPS_LOCSOFTWARE;
    dsbd.dwBufferBytes   = ppi->dwOutputBufferSize;
    dsbd.guid3DAlgorithm = GUID_NULL;
    dsbd.lpwfxFormat     = &m_waveformat; // &tblWaveFormat[nSampleFormat];

    // Create the DirectSound buffer 
	if( FAILED( hr = pDS8->CreateSoundBuffer( &dsbd, &ppi->pDSBOutput, NULL ) ) )
		return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr );

	IDirectSoundBuffer8 *pDSB8 = NULL;
	if( FAILED( hr = ppi->pDSBOutput->QueryInterface( IID_IDirectSoundBuffer8,
													(VOID**)&pDSB8 ) ) )
		return DXTRACE_ERR( TEXT("QueryInterface"), hr );

    // Create a notification event, for when the sound stops playing
    if( FAILED( hr = pDSB8->QueryInterface( IID_IDirectSoundNotify8, 
                                                    (VOID**)&ppi->pDSNotify ) ) )
        return DXTRACE_ERR( TEXT("QueryInterface"), hr );

	SAFE_RELEASE( pDSB8 );

    // Setup the notification positions
    for( INT i = 0; i < NUM_PLAY_NOTIFICATIONS; i++ )
    {
        ppi->aPosNotify[i].dwOffset = (ppi->dwNotifySize * i) + ppi->dwNotifySize - 1;
        ppi->aPosNotify[i].hEventNotify = ppi->hNotificationEvent;             
    }
    
    // Tell DirectSound when to notify us. the notification will come in the from 
    // of signaled events that are handled in WinMain()
    if( FAILED( hr = ppi->pDSNotify->SetNotificationPositions( NUM_PLAY_NOTIFICATIONS, 
                                                            ppi->aPosNotify ) ) )
        return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr );

	//ppi->dwPlayStartTime = timeGetTime();

	BYTE *pDSLockedBuffer;
	DWORD dwDSLockedBufferSize;
    // Fill the output buffer with silence at first
    // As capture data arrives, HandleNotifications() will fill
    // the output buffer with wave data.
    if( FAILED( hr = ppi->pDSBOutput->Lock( 0, ppi->dwOutputBufferSize, 
                                         (void**)&pDSLockedBuffer, &dwDSLockedBufferSize, 
                                         NULL, NULL, 0 ) ) )
        return DXTRACE_ERR( TEXT("Lock"), hr );
    
	FillMemory( (BYTE*) pDSLockedBuffer, dwDSLockedBufferSize, 
                (BYTE)( m_waveformat.wBitsPerSample == 8 ? 128 : 0 ) );


    ppi->pDSBOutput->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, NULL ); 
	}
	catch(...)
	{
		throw S_FALSE;
	}

//	if( ppi->nCodec==AUDIO_PCM )
//	{
//		ppi->dwNotifySize = XAudioPacketSize;
//		ppi->dwNotifySize -= ppi->dwNotifySize % wfx[ppi->nSampleFormat].nBlockAlign;
//	}
//	else if( ppi->nCodec==AUDIO_ADPCM )
//	{
//		//ppi->dwPlayLossSize = (DEFAULT_PACKET_SIZE>>2);// loss in 1/8
//		ppi->dwPlayLossSize = 0;
//		ppi->dwNotifySize = (XAudioPacketSize<<2) - ppi->dwPlayLossSize; 
//		ppi->dwNotifySize -= ppi->dwNotifySize % wfx[ppi->nSampleFormat].nBlockAlign;
//	}
//	else if( ppi->nCodec==AUDIO_G723 )
//	{
//		ppi->pG723Obj = g723_decoder_alloc( );
//		ppi->dwNotifySize = G723_RawBlockBytes; // 4800 20:1  g723
//		ppi->dwNotifySize -= ppi->dwNotifySize % wfx[ppi->nSampleFormat].nBlockAlign;
//	}
//	else if( ppi->nCodec==AUDIO_MULAW )
//	{
//
//		ppi->dwNotifySize =  XAudioPacketSize << 1;
//		ppi->dwNotifySize -= ppi->dwNotifySize % wfx[ppi->nSampleFormat].nBlockAlign;		
//		ppi->nSampleFormat = PCM_16BIT_8KHZ_MONO;
//	}
//	else if( ppi->nCodec==AUDIO_ALAW )
//	{
//
//		ppi->dwNotifySize =  XAudioPacketSize << 1;
//		ppi->dwNotifySize -= ppi->dwNotifySize % wfx[ppi->nSampleFormat].nBlockAlign;		
//		ppi->nSampleFormat = PCM_16BIT_8KHZ_MONO;
//	}
	


//	// Set the buffer sizes 
//	ppi->dwOutputBufferSize  = NUM_PLAY_NOTIFICATIONS * ppi->dwNotifySize;
//
//    // Create the direct sound buffer using the same format as the 
//    // capture buffer. 
//    ZeroMemory( &dsbd, sizeof(DSBUFFERDESC) );
//    dsbd.dwSize          = sizeof(DSBUFFERDESC);
//    dsbd.dwFlags         = DSBCAPS_GLOBALFOCUS|DSBCAPS_CTRLPOSITIONNOTIFY|DSBCAPS_CTRLVOLUME|
//							DSBCAPS_CTRLPAN|DSBCAPS_CTRLFREQUENCY|DSBCAPS_LOCSOFTWARE;
//    dsbd.dwBufferBytes   = ppi->dwOutputBufferSize;
//    dsbd.guid3DAlgorithm = GUID_NULL;
//    dsbd.lpwfxFormat     = &wfx[ppi->nSampleFormat];
//
//    // Create the DirectSound buffer 
//	if( FAILED( hr = pDS8->CreateSoundBuffer( &dsbd, &ppi->pDSBOutput, NULL ) ) )
//		return DXTRACE_ERR( TEXT("CreateSoundBuffer"), hr );
//
//	IDirectSoundBuffer8 *pDSB8 = NULL;
//	if( FAILED( hr = ppi->pDSBOutput->QueryInterface( IID_IDirectSoundBuffer8,
//													(VOID**)&pDSB8 ) ) )
//		return DXTRACE_ERR( TEXT("QueryInterface"), hr );
//
//    // Create a notification event, for when the sound stops playing
//    if( FAILED( hr = pDSB8->QueryInterface( IID_IDirectSoundNotify8, 
//                                                    (VOID**)&ppi->pDSNotify ) ) )
//        return DXTRACE_ERR( TEXT("QueryInterface"), hr );
//
//	SAFE_RELEASE( pDSB8 );
//
//    // Setup the notification positions
//    for( INT i = 0; i < NUM_PLAY_NOTIFICATIONS; i++ )
//    {
//        ppi->aPosNotify[i].dwOffset = (ppi->dwNotifySize * i) + ppi->dwNotifySize - 1;
//        ppi->aPosNotify[i].hEventNotify = ppi->hNotificationEvent;             
//    }
//    
//    // Tell DirectSound when to notify us. the notification will come in the from 
//    // of signaled events that are handled in WinMain()
//    if( FAILED( hr = ppi->pDSNotify->SetNotificationPositions( NUM_PLAY_NOTIFICATIONS, 
//                                                            ppi->aPosNotify ) ) )
//        return DXTRACE_ERR( TEXT("SetNotificationPositions"), hr );
//
//	//ppi->dwPlayStartTime = timeGetTime();
//
//	BYTE *pDSLockedBuffer;
//	DWORD dwDSLockedBufferSize;
//    // Fill the output buffer with silence at first
//    // As capture data arrives, HandleNotifications() will fill
//    // the output buffer with wave data.
//    if( FAILED( hr = ppi->pDSBOutput->Lock( 0, ppi->dwOutputBufferSize, 
//                                         (void**)&pDSLockedBuffer, &dwDSLockedBufferSize, 
//                                         NULL, NULL, 0 ) ) )
//        return DXTRACE_ERR( TEXT("Lock"), hr );
//    
//	FillMemory( (BYTE*) pDSLockedBuffer, dwDSLockedBufferSize, 
//                (BYTE)( wfx[ppi->nSampleFormat].wBitsPerSample == 8 ? 128 : 0 ) );
//
//    ppi->pDSBOutput->Unlock( pDSLockedBuffer, dwDSLockedBufferSize, NULL, NULL ); 

	return S_OK;

}

HRESULT CAudioDX::StartPlayer( XAUDIOINFO *pai )
{
	HRESULT hr;
	DXPLAYERINFO *ppi = (DXPLAYERINFO *)pai;
	if( ppi == NULL )
		return S_FALSE;

	if( ppi->pDSBOutput == NULL )
		return S_FALSE;
	try
	{
	
	if( FAILED( hr = ppi->pDSBOutput->Play( 0, 0, DSCBSTART_LOOPING ) ) )
		return DXTRACE_ERR( TEXT("DXStartPlayer"), hr );
	}
	catch(...)
	{
		throw S_FALSE;
	}
	return S_OK;
}

HRESULT CAudioDX::StopPlayer( XAUDIOINFO *pai )
{
	HRESULT hr;
	DXPLAYERINFO *ppi = (DXPLAYERINFO *)pai;
	if( ppi == NULL )
		return S_FALSE;

	if( ppi->pDSBOutput == NULL )
		return S_FALSE;
	try
	{
 	if( FAILED( hr = ppi->pDSBOutput->Stop( ) ) )
		return DXTRACE_ERR( TEXT("DXStopPlayer"), hr );
	}
	catch(...)
	{
		throw S_FALSE;
	}
	return S_OK;
}

HRESULT CAudioDX::PlayerSetVolume( XAUDIOINFO *pai, DWORD vol )
{
	DXPLAYERINFO *ppi			= (DXPLAYERINFO *)pai;
	HRESULT	hr;
	if( ppi == NULL )
		return S_FALSE;

	if( ppi->pDSBOutput == NULL )
		return S_FALSE;
	LONG dvol = DSBVOLUME_MIN + (LONG)(vol&0xff)*(DSBVOLUME_MAX-DSBVOLUME_MIN)/255; 
	try
	{
	
	if( FAILED( hr = ppi->pDSBOutput->SetVolume( dvol ) ) )
		return DXTRACE_ERR( TEXT("DXPlayerSetVolume"), hr );
	}
	catch(...)
	{
		throw S_FALSE;
	}
	return hr;
}

HRESULT CAudioDX::PlayerGetVolume( XAUDIOINFO *pai, DWORD *vol )
{
	DXPLAYERINFO *ppi			= (DXPLAYERINFO *)pai;
	HRESULT	hr;
	LONG dvol;
	if( ppi == NULL )
		return S_FALSE;

	if( ppi->pDSBOutput == NULL )
		return S_FALSE;
	try
	{
	
	if( FAILED( hr = ppi->pDSBOutput->GetVolume( &dvol ) ) )
		return DXTRACE_ERR( TEXT("DXPlayerSetVolume"), hr );

	}
	catch(...)
	{
		throw S_FALSE;
	}

	*vol = (DWORD)((dvol-DSBVOLUME_MIN)*255)/(DSBVOLUME_MAX-DSBVOLUME_MIN);
	*vol = *vol&0xff;
	return hr;
}

HRESULT CAudioDX::PlayerWritePacket( XAUDIOINFO *pai, XAUDIOPACKET *pkt )
{

	//TRACE("<PlayerWritePacket\n");
	//static  char decodebuf[G723_RawBlockBytes];
	HRESULT hr;
	DXPLAYERINFO *ppi			= (DXPLAYERINFO *)pai;
    VOID*   pbOutputData		= NULL;
    DWORD   dwOutputLength;
    VOID*   pbOutputData2		= NULL;
    DWORD   dwOutputLength2;
    VOID*   pbPlayData			= NULL;
	DWORD	dwLockSize			= 0;
	WORD	wCodec;

    if( NULL == ppi->pDSBOutput )
        return S_FALSE;
	
	wCodec = ppi->nCodec; // should be equal to HIWORD( pkt->fmt );
	try
	{
#if 1

	if( pkt->length==0 ) // blank data
	{
		dwLockSize = ppi->dwNotifySize;	
	}
	else
	{
		dwLockSize = pkt->length;
	}

#else
	if( pkt->length==0 ) // blank data
	{
		dwLockSize = ppi->dwNotifySize;	
	}
	else if( wCodec==AUDIO_PCM )
	{
		dwLockSize = pkt->length;	// notifysize==packetsize
	}
	else if( wCodec==AUDIO_ADPCM )
	{
		if( IS_STEREO_SAMPLE( ppi->nSampleFormat ) )
			adpcm_decoder_stereo( (char*)pkt->data, (short*)decodebuf, pkt->length, &ppi->AdpcmState );
		else
			adpcm_decoder_mono( (char*)pkt->data, (short*)decodebuf, pkt->length, &ppi->AdpcmState );

		dwLockSize = ppi->dwNotifySize;
	}
	else if( wCodec==AUDIO_G723 )
	{
		dwLockSize = g723_decode( ppi->pG723Obj, 
			(char*)pkt->data, pkt->length, 
			(short*)decodebuf, (sizeof(decodebuf)>>1) )<<1;

		if( dwLockSize<=0 || dwLockSize>sizeof(decodebuf) )
			return S_FALSE;
	}
	else if( wCodec==AUDIO_MULAW )
	{
		dwLockSize = g711_u2s( pkt->data , (unsigned char*) decodebuf , pkt->length );
		if( dwLockSize<=0 || dwLockSize>sizeof(decodebuf) )
			return S_FALSE;
	}
	else if( wCodec==AUDIO_ALAW )
	{
		dwLockSize = g711_a2s( pkt->data , (unsigned char*) decodebuf , pkt->length );
		if( dwLockSize<=0 || dwLockSize>sizeof(decodebuf) )
			return S_FALSE;
	}
#endif
    // Lock the capture buffer down
	if( FAILED( hr = ppi->pDSBOutput->Lock( ppi->dwNextOutputOffset, dwLockSize, 
                                          &pbOutputData, &dwOutputLength, 
                                          &pbOutputData2, &dwOutputLength2, 0L ) ) )
        return DXTRACE_ERR( TEXT("Play Lock"), hr );
#if 1
	if( pkt->length==0 )
	{
		FillMemory( pbOutputData, dwOutputLength,
				(BYTE)( ppi->nSampleFormat < PCM_16BIT_8KHZ_MONO ? 128 : 0 ) );
		TRACE("BLANK DATA FILLED %d bytes at %d\n", dwOutputLength, ppi->dwNextOutputOffset );
	}
	else
	{
		memcpy( pbOutputData, pkt->data, dwOutputLength );
	}
    ppi->dwNextOutputOffset += dwOutputLength; 
    ppi->dwNextOutputOffset %= ppi->dwOutputBufferSize; // Circular buffer
#else
	if( pkt->length==0 )
	{
		FillMemory( pbOutputData, dwOutputLength,
				(BYTE)( ppi->nSampleFormat < PCM_16BIT_8KHZ_MONO ? 128 : 0 ) );
		TRACE("BLANK DATA FILLED %d bytes at %d\n", dwOutputLength, ppi->dwNextOutputOffset );
	}
	else if( wCodec==AUDIO_PCM )
		memcpy( pbOutputData, pkt->data, dwOutputLength );
	else if( wCodec==AUDIO_ADPCM )
	{
		memcpy( pbOutputData, decodebuf, dwOutputLength );
		TRACE("ADPCM DATA FILLED %d bytes %d\n", dwOutputLength, ppi->dwNextOutputOffset );
	}
	else if( wCodec==AUDIO_G723 )
		memcpy( pbOutputData, decodebuf, dwOutputLength );
	else if( wCodec==AUDIO_MULAW)
		memcpy( pbOutputData, decodebuf, dwOutputLength );
		//memcpy( pbOutputData, pkt->data, dwOutputLength );
	else if( wCodec==AUDIO_ALAW)
		memcpy( pbOutputData, decodebuf, dwOutputLength );
    // Move the capture offset along
    ppi->dwNextOutputOffset += dwOutputLength; 
    ppi->dwNextOutputOffset %= ppi->dwOutputBufferSize; // Circular buffer

    if( pbOutputData2 != NULL )
    {
		if( pkt->length==0 )
			FillMemory( pbOutputData2, dwOutputLength2,
					(BYTE)( ppi->nSampleFormat < PCM_16BIT_8KHZ_MONO ? 128 : 0 ) );
		else if( wCodec==AUDIO_PCM )
			memcpy( pbOutputData2, pkt->data+dwOutputLength, dwOutputLength2 );
		else if( wCodec==AUDIO_ADPCM )
			memcpy( pbOutputData2, decodebuf+dwOutputLength, dwOutputLength2 );
		else if( wCodec==AUDIO_G723 )
			memcpy( pbOutputData2, decodebuf+dwOutputLength, dwOutputLength2 );
		else if( wCodec==AUDIO_MULAW )
			memcpy( pbOutputData2, decodebuf+dwOutputLength, dwOutputLength2 );
		else if( wCodec==AUDIO_ALAW )
			memcpy( pbOutputData2, decodebuf+dwOutputLength, dwOutputLength2 );

        // Move the capture offset along
        ppi->dwNextOutputOffset += dwOutputLength2; 
        ppi->dwNextOutputOffset %= ppi->dwOutputBufferSize; // Circular buffer
    }
#endif
    // Unlock the capture buffer
    ppi->pDSBOutput->Unlock( pbOutputData,  dwOutputLength, 
                           pbOutputData2, dwOutputLength2 );
	//TRACE(">PlayerWritePacket\n");
	}
	catch(...)
	{
		throw S_FALSE;
	}
	return S_OK;
}

void CAudioDX::FinalizePlayer( XAUDIOINFO *pai )
{
	DXPLAYERINFO *ppi = (DXPLAYERINFO *)pai;
#if 0

	if( pai->nCodec==AUDIO_G723 )
	{
		g723_decoder_free( ppi->pG723Obj );
	}
#endif
    // Release DirectSound interfaces
    SAFE_RELEASE( ppi->pDSNotify );
    SAFE_RELEASE( ppi->pDSBOutput );
}

void CAudioDX::SetPacketSize(int nsize)
{
	PacketSize = nsize;
}
